/**  
 * @Title OrderCtrl.java
 * @date 2016年4月26日 下午2:16:30
 * @Copyright (c) 2016, unibroad.com Inc. All rights reserved.
 */
package mt.ctrl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.util.Date;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.net.ssl.SSLContext;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.jfinal.aop.Before;
import com.jfinal.plugin.activerecord.tx.Tx;

import base.ctrl.BaseController;
import base.ctrl.BaseResult;
import base.jfinal.anatation.RouteBind;
import base.util.Common;
import base.util.PropertiesContent;
import mt.Const;
import mt.business.Cache;
import mt.business.UserVO;
import mt.model.Order;
import mt.model.Refund;
import mt.model.enums.OrderStatusEnum;
import mt.model.enums.RefundApplyTypeEnum;
import mt.model.enums.RefundStatusEnum;
import pay.biz.PayTypeEnum;
import pay.util.WxUtils;

/**
 * @Description 订单退款处理接口
 * @Class mt.ctrl.OrderCtrl
 * @author suan@unibroad.com
 * @version V1.0
 */
@RouteBind(path = "refund")
public class OrderRefundCtrl extends BaseController {

	/**
	 * 订单申请退款
	 * 
	 * <pre>
	 * 参数: {userCode:'',orderId:''}
	 * 
	 * <pre>
	 * 
	 * <pre>
	 * {"isSuccess":true,"message":"退款申请成功，返款会在24时内返回到支付帐号！"}
	 * </pre>
	 * 
	 * 批量退款请求参数文档：https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.
	 * 0.0.KOXiMW&treeId=66& articleId=103600&docType=1
	 */
	@Before(Tx.class)
	public void apply() {
		String userCode = this.getPara("userCode", null);
		UserVO user = Cache.GetUserVOByCode(userCode);
		String orderId = this.getPara("orderId", null);
		String memo = this.getPara("memo", null);
		if (user == null || StringUtils.isBlank(orderId)) {
			log.error("订单退款请求失败,参数错误,user=" + userCode + ",orderId=" + orderId);
			renderJson(new BaseResult<Object>(false, "操作失败，参数错误！"));
			return;
		}

		Order order = Order.dao.findById(orderId);
		if (order == null || OrderStatusEnum.getEnumByCode(order.getInt("status")) != OrderStatusEnum.PAY_SUCCESS) {
			renderJson(new BaseResult<Object>(false, "操作失败，订单当前状态不支持退款！"));
			return;
		}

		// 修改订单状态
		order.set("status", OrderStatusEnum.FUND_APPLY.getCode());
		order.set("updateTime", new Date());
		order.set("memo", "apply refund");
		boolean success = order.update();

		// 创建退款申请记录
		final Refund refund = new Refund();
		refund.set("refundId", Common.genSeriaNO());
		refund.set("orderId", order.get("orderId"));
		refund.set("applyType", RefundApplyTypeEnum.CUSTOMER_APPLY.getCode());
		refund.set("relaId", user.getUserId());
		refund.set("payment", order.getBigDecimal("payment"));
		refund.set("refundFee", order.getBigDecimal("payment"));
		PayTypeEnum payType = PayTypeEnum.getEnumByCode(order.getInt("payType"));
		refund.set("payType", payType.getCode());
		refund.set("status", RefundStatusEnum.CREATED.getCode());
		refund.set("memo", memo);
		refund.set("createTime", new Date());
		success &= refund.save();

		BaseResult<?> result = new BaseResult<Object>(success)
				.setMessage(success ? "退款申请成功，返款会在24时内返回到支付帐号！" : "操作失败，未知异常");

		// 微信退款，直接调接口实时退，
		if (payType == PayTypeEnum.WX_MOBILE) {
			wxRefund(refund);
			// new Thread(new Runnable() {
			// @Override
			// public void run() {
			// wxRefund(refund);
			// }
			// }, "wx-refund-" + orderId);
		}

		renderJson(result.toJsonString());
	}

	/**
	 * 微信退款
	 * 
	 * @param refund
	 * @throws IOException
	 */
	private void wxRefund(Refund refund) {

		String appId = PropertiesContent.get(Const.WXPAY_MSG_KEY_APP_ID);
		String mch_id = PropertiesContent.get(Const.WXPAY_MSG_KEY_wxpay_mct_id);
		String apiKey = PropertiesContent.get(Const.WXPAY_MSG_KEY_wxpay_api_key);

		SortedMap<String, Object> paramsMap = new TreeMap<String, Object>();
		paramsMap.put("appid", appId);
		paramsMap.put("mch_id", mch_id);
		paramsMap.put("device_info", "WEB");
		paramsMap.put("nonce_str", System.nanoTime() + "" + new Random().nextInt(10));
		paramsMap.put("out_trade_no", refund.get("orderId"));
		paramsMap.put("out_refund_no", refund.get("refundId"));
		paramsMap.put("total_fee", refund.getBigDecimal("payment"));
		paramsMap.put("refund_fee", refund.getBigDecimal("refundFee"));
		paramsMap.put("op_user_id", mch_id);
		String sign = null;
		try {
			sign = WxUtils.getSign(paramsMap, apiKey, "utf-8");
		} catch (Exception e) {
			log.error("微信退款申请失败，处理加签异常", e);
		}
		if (StringUtils.isBlank(sign)) {
			refund.set("status", RefundStatusEnum.FAILURE.getCode());
			refund.set("memo", "退款失败，接口签名异常");
			refund.set("updateTime", new Date());
			refund.save();
			return;
		}
		paramsMap.put("sign", sign);

		String reuqestXml = WxUtils.getReqXml(paramsMap);
		CloseableHttpClient httpclient = null;
		try {
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			String keystoreFile = getClass().getResource("/apiclient_cert.p12").getFile();
			System.out.println("keystoreFile == " + keystoreFile);
			FileInputStream instream = new FileInputStream(keystoreFile);
			// new File("‪D:/java/workspace/mitao/cert/apiclient_cert.p12"));//
			// 放退款证书的路径
			try {
				keyStore.load(instream, mch_id.toCharArray());
			} finally {
				instream.close();
			}
			SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" },
					null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

			HttpPost httpPost = new HttpPost(PropertiesContent.get(Const.WXPAY_MSG_KEY_refund_url));// 退款接口

			System.out.println("executing request" + httpPost.getRequestLine());
			StringEntity reqEntity = new StringEntity(reuqestXml);
			// 设置类型
			reqEntity.setContentType("application/x-www-form-urlencoded");
			httpPost.setEntity(reqEntity);
			CloseableHttpResponse response = httpclient.execute(httpPost);
			try {
				HttpEntity entity = response.getEntity();
				System.out.println("----------------------------------------");
				System.out.println(response.getStatusLine());
				if (entity != null) {
					System.out.println("Response content length: " + entity.getContentLength());
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(entity.getContent(), "UTF-8"));
					String text;
					while ((text = bufferedReader.readLine()) != null) {
						System.out.println(text);
					}

				}
				EntityUtils.consume(entity);
			} finally {
				response.close();
			}
		} catch (Exception e) {
			log.error("aaaaa", e);
		} finally {
			if (httpclient != null) {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	/// 退款申请接口
	///

	///
	// public JsonResult Refund(TRADE_Model trade)
	// {
	// string nonceStr =
	// Senparc.Weixin.MP.TenPayLibV3.TenPayV3Util.GetNoncestr();
	//
	// Senparc.Weixin.MP.TenPayLibV3.RequestHandler packageReqHandler = new
	// Senparc.Weixin.MP.TenPayLibV3.RequestHandler(null);
	//
	// //设置package订单参数
	// packageReqHandler.SetParameter("appid", AppId); //公众账号ID
	// packageReqHandler.SetParameter("mch_id", MchId); //商户号
	// packageReqHandler.SetParameter("out_trade_no", trade.TRADE_NO); //填入商家订单号
	// packageReqHandler.SetParameter("out_refund_no", ""); //填入退款订单号
	// packageReqHandler.SetParameter("total_fee", ""); //填入总金额
	// packageReqHandler.SetParameter("refund_fee", ""); //填入退款金额
	// packageReqHandler.SetParameter("op_user_id", MchId); //操作员Id，默认就是商户号
	// packageReqHandler.SetParameter("nonce_str", nonceStr); //随机字符串
	//
	// string sign = packageReqHandler.CreateMd5Sign("key", Key);
	//
	// packageReqHandler.SetParameter("sign", sign); //签名
	//
	// //退款需要post的数据
	// string data = packageReqHandler.ParseXML();
	//
	// //退款接口地址
	// string url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
	//
	// //本地或者服务器的证书位置（证书在微信支付申请成功发来的通知邮件中）
	// string cert = "D:\\apiclient_cert.p12";
	//
	// //私钥（在安装证书时设置）
	// string password = "";
	//
	// ServicePointManager.ServerCertificateValidationCallback = new
	// RemoteCertificateValidationCallback(CheckValidationResult);
	// //调用证书
	// X509Certificate2 cer = new X509Certificate2(cert, password,
	// X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);
	//
	// #region 发起post请求
	// HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(url);
	// webrequest.ClientCertificates.Add(cer);
	// webrequest.Method = "post";
	//
	// byte[] postdatabyte = Encoding.UTF8.GetBytes(data);
	// webrequest.ContentLength = postdatabyte.Length;
	// Stream stream;
	// stream = webrequest.GetRequestStream();
	// stream.Write(postdatabyte, 0, postdatabyte.Length);
	// stream.Close();
	//
	// HttpWebResponse httpWebResponse =
	// (HttpWebResponse)webrequest.GetResponse();
	// StreamReader streamReader = new
	// StreamReader(httpWebResponse.GetResponseStream());
	// string responseContent = streamReader.ReadToEnd();
	// #endregion
	//
	// var res = System.Xml.Linq.XDocument.Parse(responseContent);
	// string return_code = res.Element("xml").Element("return_code").Value;
	//
	// Hashtable hashtable = new Hashtable();
	//
	// hashtable.Add("return_code", return_code);
	//
	// return Json(hashtable);
	// }
	//
	// private static bool CheckValidationResult(object sender, X509Certificate
	// certificate, X509Chain chain,
	// SslPolicyErrors errors) {
	// if (errors == SslPolicyErrors.None)
	// return true;
	// return false;
	// }

}
